﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MaxLeaf.Common;
using MaxLeaf.DB;
using System.Data;
using System.Transactions;
using MaxLeaf.DAL.DEL;

namespace MaxLeaf.DAL
{
    /// <summary>
    /// 所有的分发操作入口，比如checklog
    /// </summary>
    public class DALFactory
    {
        public void CheckLog(ServerInfo server)
        {
            CheckLog(server,null);
        }
        public void CheckLog(ServerInfo server, DataView dvOld)
        {
            
            bool blnNeedCheckAgain = false;
            DataView dv = null;
            DataTable dt = null;

            using (DBAccess dbcon = new DBAccess(server))
            {
                dt=dbcon.GetDataTable(GetLogSQL(server.Type));
            }
            if (dt == null)
            {
                if (server.Type == ServerType.Web)
                {
                    CheckLog(ServerInfo.GetK3MasterServer());
                }
                return;
            }
            if (dt.Rows.Count == 0)
            {
                if (server.Type == ServerType.Web)
                {
                    CheckLog(ServerInfo.GetK3MasterServer());
                }
                return ;
            }
            dv = dt.DefaultView;

            if (dvOld!=null)
            {
                //mLog全部跑一遍后，再读一次，判断有没有新log
                if (dvOld.Count == dv.Count 
                    && CvtFunc.ToString(dvOld[0][LogDEL.RecId]).Equals(CvtFunc.ToString(dv[0][LogDEL.RecId]))
                    && CvtFunc.ToString(dvOld[dvOld.Count - 1][LogDEL.RecId]).Equals(CvtFunc.ToString(dv[dv.Count-1][LogDEL.RecId])))
                {
                    if (server.Type == ServerType.Web)
                    {
                        CheckLog(ServerInfo.GetK3MasterServer());
                    }
                    return ;
                }
            }
            blnNeedCheckAgain = true;

            

            foreach (KeyValuePair<string, ICheckLog> kvp in GetCheckType())
            {
                dv.RowFilter = string.Format("{0}='{1}'", LogDEL.LogType, kvp.Key);
                if (dv.Count > 0)
                {
                    //根据logtype调用实际操作类
                    CheckLog(server, dv, kvp.Value);
                }
            }


            

            if (blnNeedCheckAgain)
            {
                //再读一次，看有没有新数据
                dv.RowFilter = "";
                CheckLog(server,dv);
            }

            if(server.Type== ServerType.Web )
            {
                CheckLog(ServerInfo.GetK3MasterServer());
            }
        }

        /// <summary>
        /// 所有dalbulider,与logtype对应
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, ICheckLog> GetCheckType()
        {
            return new Dictionary<string, ICheckLog>
            {
                {LogType.goods_main.ToString(), new ImInvMasterDALBuilder() }
                ,{LogType.ImInvGroup_1.ToString(), new ImInvGroup_1DALBuilder() }
                 ,{LogType.ImInvGroup_2.ToString(), new ImInvGroup_2DALBuilder() }

                ,{LogType.t_MeasureUnit.ToString(), new t_MeasureUnitDALBuilder() }  
                ,{LogType.t_UnitGroup.ToString(), new t_UnitGroupDALBuilder() }  

                ,{LogType.goods_brand.ToString(), new goods_brandDALBuilder() } 
                ,{LogType.goods_category.ToString(), new goods_categoryDALBuilder() } 

                 ,{LogType.goods_barcode.ToString(), new goods_barcodeDALBuilder() } 

                 ,{LogType.t_Base_Emp.ToString(), new t_Base_EmpDALBuilder() } 
                 ,{LogType.t_Department.ToString(), new t_departmentDALBuilder() } 
                
                ,{LogType.user_main.ToString(), new arCustomerDALBuild() } 
                ,{LogType.region_mdc.ToString(), new region_mdcDALBuildercs() }
                ,{LogType.order_main.ToString (), new SEOrderDALBuilder()}  
                ,{LogType.SEOutStockChecked.ToString (), new SEOutStockCheckedDALBuilder()}  
                ,{LogType.ICStockBillChecked.ToString (), new ICStockBillCheckedDALBuilder()}  
                ,{LogType.ICSaleChecked.ToString (), new ICSaleCheckedDALBuilder()}  
                ,{LogType.ICSaleUnChecked.ToString (), new ICSaleUnCheckedDALBuilder()}  
                ,{LogType.RedICStockBillDeleted.ToString (), new RedICStockBillDeletedDALBuilder()}  
                ,{LogType.t_icItemDeleted.ToString (), new t_icItemDeletedDALBuilder()}  
            };

        }

        private void CheckLog(ServerInfo server, DataView dv, ICheckLog checker)
        {

            Dictionary<string, bool> dictLog = new Dictionary<string, bool>();
            foreach (DataRowView drv in dv)
            {
                
                    string key = GetLogKey(drv);
                    bool blnOK = false;

                    if (!dictLog.ContainsKey(key) || NeedCheckLog(dictLog, drv, out blnOK))
                    {
                        //如果需要处理log                         
                            try
                            {

                               
                                blnOK = checker.CheckLog(server , drv);

                                if (blnOK)
                                {
                                    LogManager.Info(GetLogInfo(InFoType.CheckLog, drv));
                                     ;
                                }

                            }
                            catch (Exception ex)
                            {
                               
                                blnOK = false;
                                LogManager.Error(ex);
                            }
                        


                        //保存处理过的mLog
                        if (!dictLog.ContainsKey(key))
                        {
                            dictLog.Add(key, blnOK);
                        }

                    }
                    else
                    {

                        if (!dictLog.ContainsKey(key))
                        {
                            dictLog.Add(key, blnOK);
                        }
                    }

                    if (dictLog[key])
                    {
                        try
                        {


                            DeleteLog(GetDeleteLogServer(server), drv);
                                 
                             
                            LogManager.Info(GetLogInfo(InFoType.DeleteLog, drv));
                        }
                        catch (Exception ex)
                        {
                            LogManager.Error(ex);
                        }

                    }
                }
            
        }

        private ServerInfo GetDeleteLogServer(ServerInfo server)
        {
            if (server.Type == ServerType.Web)
            {
                return server.WriteDB;
            }
            else
            {
                return server;
            }
        }

        private void DeleteLog(ServerInfo server, DataRowView drv)
        {
            using (DBAccess dbcon = new DBAccess(server))
            {
                KeyValuePair<string, IDataParameter[]> kvp=dbcon.CreateCondParam(new Dictionary<string, object>{ {"recid",drv["Recid"] } });
                dbcon.ExecuteSql(string.Format("delete  from {0} where {1}", LogDEL.GetLogTableName(server.Type), kvp.Key), kvp.Value);
            }
        }

        

       

       

        public static string GetLogInfo(InFoType infoType, System.Data.DataRowView drv)
        {
            string strMsg = string.Empty;
            switch (infoType)
            {
                case InFoType.CheckLog:
                    strMsg = string.Format("Checked log:{0}_{1}_{2}_{3}", drv[DEL.LogDEL.LogType], drv[DEL.LogDEL.KeyValue], drv[DEL.LogDEL.LogStatus], drv[DEL.LogDEL.UpdateMode]);
                    break;
                case InFoType.DeleteLog:
                    strMsg = string.Format("Deleted log:{0}_{1}_{2}_{3}", drv[DEL.LogDEL.LogType], drv[DEL.LogDEL.KeyValue], drv[DEL.LogDEL.LogStatus], drv[DEL.LogDEL.UpdateMode]);
                    break;
            }

            return strMsg;
        }

        /// <summary>
        /// 有些mLog不需要处理，因为同一批次已经处理过了
        /// </summary>
        /// <param name="dictLog"></param>
        /// <param name="drv"></param>
        /// <param name="blnOK"></param>
        /// <returns></returns>
        private bool NeedCheckLog(Dictionary<string, bool> dictLog, DataRowView drv, out bool blnOK)
        {
            LogStatus status = (LogStatus)CvtFunc.ToInt(drv[DEL.LogDEL.LogStatus]);
            bool blnRT = true;
            blnOK = true;
            string strKey = string.Empty;
            if (status == LogStatus.Add)
            {
            }
            else if (status == LogStatus.Update)
            {
                strKey = GetLogKey(CvtFunc.ToString(drv[DEL.LogDEL.LogType]), CvtFunc.ToString(drv[DEL.LogDEL.KeyValue]), (int)LogStatus.Add);

                if (dictLog.ContainsKey(strKey) && dictLog[strKey])
                {
                    blnRT = false;
                }
            }
            else if (status == LogStatus.Delete)
            {
            }

            if (blnRT)
            {
                strKey = GetLogKey(drv);
                //因为一条记录会写3次log，所以干脆出错一次就剩下的同条log都不判断，等待下次
                if(dictLog.ContainsKey(strKey) )// (dictLog.ContainsKey(strKey) && dictLog[strKey])
                {
                    blnRT = false;
                }
            }

            return blnRT;

        }

        private string GetLogKey(DataRowView drv)
        {
            return GetLogKey(CvtFunc.ToString(drv[DEL.LogDEL.LogType ]), CvtFunc.ToString(drv[DEL.LogDEL.KeyValue]), CvtFunc.ToInt(drv[DEL.LogDEL.LogStatus]));
        }

        private string GetLogKey(string strLogType,string strKeyValue, int intLogStatus)
        {
            return string.Format("{0}_|_{1}_|_{2}", strLogType, strKeyValue, intLogStatus);
        }

        private   string GetLogSQL(ServerType serverType)
        {
            return string.Format(@"select * from {0} order by recid", LogDEL.GetLogTableName(serverType));
        }
    }
}
